package com.guet.careapp.dao.base;


import com.guet.careapp.utils.ClearSetUtil;
import com.guet.careapp.utils.Convertor;
import com.guet.careapp.utils.Info;
import com.guet.careapp.utils.PageBean;
import com.guet.careapp.utils.PageQueryModel;
import com.guet.careapp.utils.StringMap;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;

@SuppressWarnings("unchecked")
@Transactional
public abstract class DaoSupportImpl<T> implements DaoSupport<T> {

    @Resource
    private SessionFactory sessionFactory;

    protected Class<T> clazz = null;

    public DaoSupportImpl() {
        // 通过反射获取泛型的真实类
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.clazz = (Class<T>) type.getActualTypeArguments()[0];
    }

    @Override
    public T findByField(Map<String, Object> fieldMap) {
        List<T> list = findAllByField(fieldMap);
        if (list.size() > 0) {
            if (list.size() > 1) {
                Info.printError("请求查询一个实体，结果集大于1");
            }
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<T> findAllByField(Map<String, Object> fieldMap) {
        String head = "from  " + clazz.getCanonicalName();
        StringBuffer queryCondition = new StringBuffer();
        // 拼凑查询条件----
        // 转换Map
        List<StringMap> mapToList = Convertor.MapToList(fieldMap);
        if (fieldMap.size() > 0) {
            // 方便遍历，第一个特殊（无"and")
            queryCondition.append(" where " + mapToList.get(0).key + "=:" + mapToList.get(0).key);
            if (mapToList.size() > 1) {
                for (int i = 1; i < mapToList.size(); i++) {
                    queryCondition.append(" and " + mapToList.get(i).key + "=:" + mapToList.get(i).key);
                }
            }
        }
        String hql = head + queryCondition.toString();
        // Info.print("拼凑之后的hql:" + hql);
        Session session = getSession();
        Query query = session.createQuery(hql);
        // 给查询语句添加值
        if (fieldMap.size() > 0) {
            for (String key : fieldMap.keySet()) {
                @SuppressWarnings("unused")
                String fieldType = fieldMap.get(key).getClass().getTypeName();
                query.setParameter(key, fieldMap.get(key));
            }
        }

        List<T> list = query.list();

        return list;
    }

    protected Session getSession() {
        // return sessionFactory.openSession();
        return sessionFactory.getCurrentSession();
    }

    @Override
    public Serializable save(T entity) throws Exception {
        Serializable saveResult = null;
        saveResult = getSession().save(entity);
        System.out.println("保存之后的返回值：" + saveResult);
        return saveResult;
    }

    @Override
    public List<T> findAll() {
        String hql = "from " + clazz.getName();
        Query query = getSession().createQuery(hql);
        List<T> list = query.list();
        return list;
    }

    @Override
    public void deleteById(Integer id) throws Exception {
        T entity = (T) getSession().get(clazz, id);
        if (entity != null) {
            ClearSetUtil.clearSet(entity.getClass(), entity);
            Session s = getSession();
            s.delete(entity);
            s.flush();
        }
    }

    @Override
    public void deleteByField(Map<String, Object> fieldMap) throws Exception {
        T entity = findByField(fieldMap);
        if (entity != null) {
            ClearSetUtil.clearSet(entity.getClass(), entity);
            Session s = getSession();
            s.delete(entity);
            s.flush();
        }
    }

    @Override
    public T findById(Integer id) {
        return (T) getSession().get(clazz, id);
    }

    @Override
    public void update(T entity) throws Exception {
        Session s = getSession();
        s.update(entity);
        s.flush();
    }

    @Override
    public void saveOrUpdate(T entity) throws Exception {
        getSession().saveOrUpdate(entity);
    }

    @Override
    public List<T> queryByHql(String hql) {
        Query query = getSession().createQuery(hql);
        List<T> list = query.list();
        return list;
    }

    @Override
    public PageBean queryPageData(PageQueryModel pageQueryModel) {
        // 赋值PageQueryModel里的Class
        pageQueryModel.setClazz(clazz);
        // 查询一页的数据列表
        Query query = getSession().createQuery(pageQueryModel.getListHql());
        int startNum = (pageQueryModel.getCurrentPage() - 1) * pageQueryModel.getPageSize();
        int endNum = startNum + pageQueryModel.getPageSize() - 1;
        query.setFirstResult(startNum);
        query.setMaxResults(pageQueryModel.getPageSize());
        // 添加查询条件
        Map<String, Object> map = pageQueryModel.getParameters();
        for (String key : map.keySet()) {
            query.setParameter(key, map.get(key));
            System.out.println("查询条件：" + key + "  :" + map.get(key));
        }
        List list = query.list();
        Info.print("起始条数：" + startNum + "~" + endNum + "  listSize:" + list.size());

        query = getSession().createQuery(pageQueryModel.getCountHql());
        for (String key : map.keySet()) {
            query.setParameter(key, map.get(key));
        }
        Long recordCount = (Long) query.uniqueResult();
        PageBean pageBean = new PageBean(pageQueryModel.getCurrentPage(), pageQueryModel.getPageSize(),
                recordCount.intValue(), list);
        return pageBean;
    }

    @Override
    public int getMaxField(String fieldName) {
        String hql = "select max(" + fieldName + ") from " + clazz.getName();
        System.out.println(hql);
        int maxValue = (int) getSession().createQuery(hql).uniqueResult();
        return maxValue;
    }

    @Override
    public Serializable merge(T entity) {
        Serializable saveResult = (Serializable) getSession().merge(entity);
        System.out.println("保存之后的返回值：" + saveResult);
        return saveResult;
    }

    @Override
    public void deleteEnity(T entity) {
        if (entity != null) {
            ClearSetUtil.clearSet(entity.getClass(), entity);
            getSession().delete(entity);
        }
    }

    @Override
    public List<T> queryByHQLWithLimit(String hql, int limit) {
        Query query = getSession().createQuery(hql);
        query.setFirstResult(0);
        query.setMaxResults(100);
        List<T> list = query.list();
        return list;
    }
}
